iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 8
2
自我挑戰組

JavaScript 試煉之旅系列 第 8

JavaScript 物件(Object)

  • 分享至 

  • xImage
  •  

今天要學習的是物件(Object),事不宜遲,開始學習吧!

物件的特性與存取

在物件中,每個特性都有一組對應的名稱(key)與值(value),如下式程式碼的 nameBill

要注意的是物件中的特性並不是用;的方式區隔,而會以,的隔開每個特性。

// name 為特性(key),而 Bill 為值(value)。
var obj = {
    name: 'Bill',
    habbit: 'play computer'
};

對於物件特性的取值方式則有兩種:

  • 透過 .特性存取
  • 透過[" "]鍵值存取

Ex: 透過 . 的方式取值

var obj = {
    name: 'Bill',
    habbit: 'play computer'
};
console.log(obj.name);

Ex2: 透過 [" "] 的方式取值

var obj = {
    name: 'Bill',
    habbit: 'play computer'
};
console.log(obj["habbit"]);

而存值的方式也不困難,如下:

Ex: 透過 . 的方式存值

var obj = {};
obj.name = 'Bill';
console.log(obj);

Ex2: 透過 [" "] 的方式存值

var obj = {};
obj["habbit"] = 'play computer';
console.log(obj);

物件的方法

用比較簡單的方式來講,就是在物件中使用函式(function),就稱為使用物件的方法。

Ex: 調用 obj 物件的方法 sayHi()

var obj = {
    name: 'Bill',
    sayHi: function(){
        console.log(`Hello! ${this.name}`);
    }
}
obj.sayHi();

關於原型的二三事

這個部分要學習關於物件比較深入的部份:原型

Object.prototype.__proto__

先來看看 ECMAScript 2015(第6版,ECMA-262)怎麼解釋它:

Object.prototype.proto is an accessor property with attributes { [[Enumerable]]: false, [[Configurable]]: true }. The [[Get]] and [[Set]] attributes are defined as follows

從規範中可以知道, __proto__ 是一個訪問器屬性(一個 getter 函數及一個 setter 函數),且為不可列舉(Enumerable)、可配置(Configurable)的。

MDN 對於 Object.prototype.__proto__ 則有寫到:

The proto property of Object.prototype is an accessor property (a getter function and a setter function) that exposes the internal [[Prototype]] (either an object or null) of the object through which it is accessed.

前半段與 ECMAScript 2015(第6版,ECMA-262)所提相同,但後半段則提到可以透過 Object.prototype.__proto__ 來訪問內部的 [[Prototype]],而這個內部的 [[Prototype]] 可能是一個物件(Object),也可能為空(null)。

來看看幾個測試的例子:

var obj = {age: 2};
console.log(obj.__proto__);
console.log(Object.prototype);

8-2

使用 Object.prototype 語法可以得到一個原型物件,從結果可以看到 obj.__proto__ 可以取得與 Object.prototype 相同的結果。

而且與剛剛MDN所提及的可以透過 Object.prototype.__proto__ 來訪問內部的 [[Prototype]] 相呼應。

但是,雖然這個語法可以達成這個目的,使用它卻是有爭議的。

使用 Object.prototype.__proto__ 改變物件屬性,這種行為在每一個JavaScript引擎和瀏覽器中都是一個非常慢且影響性能的操作。

然而為了確保瀏覽器的兼容性(許多瀏覽器都有實作該功能),Object.prototype.__proto__ 於 ES6 中被標準化。

但即使如此依然不推薦使用。

因此,如果有操作原型物件的需求,應該使用 Object.getPrototypeOfObject.setPrototypeOf 語法。

Object.getPrototypeOfObject.setPrototypeOf 語法等同於 Object.prototype.__proto__ 的 getter 函數 與 setter 函數。

var obj = {age: 2};
console.log(obj.__proto__);
console.log(Object.getPrototypeOf(obj));

原型(prototype)

object that provides shared properties for other objects
ECMAScript 2015(第6版,ECMA-262)

原型(prototype)可以分享自己的特性給其他物件使用。

而所有的物件都有原型(prototype)

來看看某個物件的原型物件

const obj = {name: "Bill"};
console.log(obj);

可以看到 obj 物件的原型物件,而其中諸如 isPrototypeOf 等這些特性,都是這個原型物件分享給 obj 物件使用的特性。

8-1

再看看另外一個例子:

const numberArray = [1,2];
console.log(numberArray);

numberArray 的底層有一個陣列原型物件,而 numberArray 這個陣列之所以可以使用陣列的方法(諸如 reducefiltermap 等),就是因為從陣列原型物件中繼承了這些方法。

8-3

原型鏈(prototype chain)

再來讓我們透過例子理解原型鏈的概念:

這邊要注意的是這樣的寫法只適用於測試,實務運用會導致瀏覽器效能降低

Ex. 透過 __proto__obj 物件做為原型物件 assign(指定給) obj2 物件

const obj = {
  sayHi: function() {
    console.log('Hello!');
  }
}

const obj2 = {};

obj2.__proto__ = obj;
obj2.sayHi();

obj 原型鏈搜尋sayHi()方法的過程如下:

  1. obj2 物件在自己的特性找不到 sayHi 這個方法時,會往原型物件中尋找該方法
  2. 發現在下一層的原型物件中找到 sayHi 這個方法(因為剛剛已經將 obj 物件當作原型物件傳給 obj2)
  3. obj2 使用 sayHi 這個方法並回傳 Hello

之所以能夠不斷往原型物件尋找特性,就是因為原型鏈(prtotype chain)的概念

來看看 MDN 對於原型鏈(prtotype chain)的解釋:

每個物件都有一個連著其他原型(prototype)的私有屬性(private property)物件。原型物件也有著自己的原型,於是原型物件就這樣鏈結,直到撞見 null 為止:null 在定義裡沒有原型、也是原型鏈(prototype chain)的最後一個鏈結。

那如果當原型物件與物件自身都有同樣的屬性時,會是得到怎麼樣的結果呢?

以這個例子來說明:

const obj = {
  name: "Bill",
  sayHi: function(){
    console.log('Hello!');
  }
}

const obj2  = {
  name: "John"
};

console.log(obj2.name);

可以發現獲得的值是 obj2 特性 name 的值 John。所以可以知道:

物件會由原型鏈最上方開始尋找,當符合條件時就停止,所以會找到 John 的名字而不是 Bill 這個名字

關於物件(Object)今天先告一段落,明天繼續介紹物件(Object)的其他部分。

明天見~


上一篇
JavaScript 陣列(Array)的方法 Part 3
下一篇
物件(Object)的方法 Part 1
系列文
JavaScript 試煉之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
RURU Tseng
iT邦新手 2 級 ‧ 2019-09-23 20:23:37

終於到物件篇了~趕緊拿起筆記本筆記,好文推推!

鐵人賽結束一個月後,我才來追進度,超慢的

我要留言

立即登入留言